Crate binggan

Source
Expand description

§Binggan (餅乾, bǐng gān) - A Benchmarking Library for Stable Rust

Binggan is a benchmarking library designed for flexibility, providing fast and stable results. It reports peak memory consumption and can integrate with perf for hardware performance counters.

§Main Components

Binggan has two primary entry points for running benchmarks:

  • BenchRunner: A main runner for. Useful for single benchmarks or to create groups.
  • InputGroup: Use this when running a group of benchmarks with the same inputs, where ownership of inputs can be transferred.

Otherwise if you need more flexibility you can use BenchGroup via BenchRunner::new_group.

See https://github.com/PSeitz/binggan/tree/main/benches for examples. benches/bench_group.rs and benches/bench_input_group.rs are different ways to produce the same output.

§OutputValue

The typical benchmarking flow involves providing some input, processing it through a function, and obtaining an output. Benchmarks return OutputValue, which represents the result of the benchmark. This output can be particularly useful in scenarios like compression benchmarks, where it reports the output size or other relevant metrics.

§Plugins

See the plugins module for more information on how to register custom plugins.

§Reporting

See the report module for more information on how to customize the benchmark result reporting.

§Perf Integration

Binggan can integrate with perf to report hardware performance counters. See PerfCounterPlugin for more information.

§Example for InputGroup

use binggan::{black_box, InputGroup, PeakMemAlloc, INSTRUMENTED_SYSTEM, plugins::*};

#[global_allocator]
pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;

fn main() {
    // Tuples of name and data for the inputs
    let data = vec![
        (
            "max id 100; 100 el all the same",
            std::iter::repeat(100).take(100).collect(),
        ),
        (   
            "max id 100; 100 el all different",
            (0..100).collect()
        ),
    ];
    bench_group(InputGroup::new_with_inputs(data));
}

// Run the benchmark for the group with input `Vec<usize>`
fn bench_group(mut runner: InputGroup<Vec<usize>, u64>) {
    runner
       // Set the peak mem allocator. This will enable peak memory reporting.
       .add_plugin(PeakMemAllocPlugin::new(GLOBAL))
       .add_plugin(PerfCounterPlugin::default());
    runner.register("vec", move |data| {
        let vec = test_vec(data);
        vec.len() as u64
    });
    runner.register("hashmap", move |data| {
        let map = test_hashmap(data);
        map.len() as u64
    });
   runner.run();
}

fn test_vec(data: &Vec<usize>) -> Vec<usize> {
    let mut vec = Vec::new();
    for idx in data {
        if vec.len() <= *idx {
            vec.resize(idx + 1, 0);
        }
        vec[*idx] += 1;
    }
    black_box(vec)
}
fn test_hashmap(data: &Vec<usize>) -> std::collections::HashMap<usize, i32> {
    let mut map = std::collections::HashMap::new();
    for idx in data {
        *map.entry(*idx).or_insert(0) += 1;
    }
    black_box(map)
}

§Example for BenchGroup

use std::collections::HashMap;

use binggan::{black_box, plugins::*, BenchRunner, PeakMemAlloc, INSTRUMENTED_SYSTEM};

#[global_allocator]
pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;

fn test_vec(data: &Vec<usize>) -> Vec<i32> {
    let mut vec = Vec::new();
    for idx in data {
        if vec.len() <= *idx {
            vec.resize(idx + 1, 0);
        }
        vec[*idx] += 1;
    }
    vec
}
fn test_hashmap(data: &Vec<usize>) -> HashMap<&usize, i32> {
    let mut map = std::collections::HashMap::new();
    for idx in data {
        *map.entry(idx).or_insert(0) += 1;
    }
    map
}

fn run_bench() {
    let inputs: Vec<(&str, Vec<usize>)> = vec![
        (
            "max id 100; 100 el all the same",
            std::iter::repeat(100).take(100).collect(),
        ),
        ("max id 100; 100 el all different", (0..100).collect()),
    ];
    let mut runner: BenchRunner = BenchRunner::new();

    runner
       // Set the peak mem allocator. This will enable peak memory reporting.
       .add_plugin(PeakMemAllocPlugin::new(GLOBAL))
       .add_plugin(CacheTrasher::default());

    let mut group = runner.new_group();
    for (input_name, data) in inputs.iter() {
        group.set_input_size(data.len() * std::mem::size_of::<usize>());
        group.register_with_input("vec", data, move |data| {
            black_box(test_vec(data));
        });
        group.register_with_input("hashmap", data, move |data| {
            black_box(test_hashmap(data));
        });
    }
    group.run();
}

fn main() {
    run_bench();
}

Modules§

plugins
The module to define custom plugins The plugin system works by registering to events.
report
The module to report benchmark results

Structs§

BenchGroup
BenchGroup is a group of benchmarks wich are executed together.
BenchId
BenchId is a unique identifier for a benchmark. It has three components:
BenchResult
The result of a single benchmark.
BenchRunner
The main struct to run benchmarks.
Config
Configure the benchmarking options.
InputGroup
InputGroup<Input, OutputValue> is a collection of benchmarks that are run with the same inputs.
PeakMemAlloc
An allocator middleware which keeps track of peak memory consumption.

Statics§

INSTRUMENTED_SYSTEM
An instrumented instance of the system allocator.

Traits§

OutputValue
Every bench returns an OutputValue, which can be formatted to a string.
PeakMemAllocTrait
The PeakAllocTrait trait provides a common interface for all allocators.

Functions§

black_box
A function that is opaque to the optimizer, used to prevent the compiler from optimizing away computations in a benchmark. An identity function that hints to the compiler to be maximally pessimistic about what black_box could do.